package com.lago;

import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 客户端监控服务调用时常
 */
@Activate(group = {"consumer"})
public class TPMonitorFilter implements Filter , Runnable{
    private  final Map<Long, Long> THREAD_METHODA = new ConcurrentHashMap<>();
    private  final Map<Long, Long> THREAD_METHODB = new ConcurrentHashMap<>();
    private  final Map<Long, Long> THREAD_METHODC = new ConcurrentHashMap<>();

    public TPMonitorFilter(){
        // 每隔5秒打印一次
        Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(this,1,5, TimeUnit.SECONDS);
    }

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        //获取调用方法名
        String methodName = invocation.getMethodName();
        String serviceName= invocation.getServiceName();
        if(!"com.lagou.service.TestService".equals(serviceName)){
            return invoker.invoke(invocation);
        }
        Long start = System.currentTimeMillis();
        try{
           return  invoker.invoke(invocation);
        }catch (Exception e){

        }finally {
            Long end = System.currentTimeMillis();
            //System.out.println("方法"+methodName+"调用时长为："+String.valueOf(end-start) +"毫秒");
            if("methodA".equals(methodName)){
                THREAD_METHODA.put(end,end-start);
            }else if("methodB".equals(methodName)){
                THREAD_METHODB.put(end,end-start);
            }else if("methodC".equals(methodName)){
                THREAD_METHODC.put(end,end-start);
            }
        }
        return null;
    }

    @Override
    public void run() {

        Long now = System.currentTimeMillis();

        //计算methodA在最近一分钟的调用次数；
        //计算methodA在最近一分钟的调用次数；
        List<Long> list1 = new ArrayList<>();
        for(Map.Entry<Long, Long> entry:THREAD_METHODA.entrySet()){
            //大于1分钟的不做保存
            if(now-entry.getKey()>600000) {
                THREAD_METHODA.remove(entry.getKey());
            }else{
                list1.add(entry.getValue());
            }
        }


        List<Long> list2 = new ArrayList<>();
        for(Map.Entry<Long, Long> entry:THREAD_METHODB.entrySet()){
            //大于1分钟的不做保存
            if(now-entry.getKey()>600000) {
                THREAD_METHODB.remove(entry.getKey());
            }else{
                list2.add(entry.getValue());
            }
        }

        //计算methodC在最近一分钟的调用次数；
        List<Long> list3 = new ArrayList<>();
        for(Map.Entry<Long, Long> entry:THREAD_METHODC.entrySet()){
            //大于1分钟的不做保存
            if(now-entry.getKey()>600000) {
                THREAD_METHODC.remove(entry.getKey());
            }else{
                list3.add(entry.getValue());
            }
        }

        Collections.sort(list1, new Comparator<Long>() {
            @Override
            public int compare(Long o1, Long o2) {
                return  Integer.valueOf((o1-o2)+"");
            }
        });

        Collections.sort(list2, new Comparator<Long>() {
            @Override
            public int compare(Long o1, Long o2) {
                return  Integer.valueOf((o1-o2)+"");
            }
        });

        Collections.sort(list3, new Comparator<Long>() {
            @Override
            public int compare(Long o1, Long o2) {
                return  Integer.valueOf((o1-o2)+"");
            }
        });
        int a = (int)(list1.size()*0.9);
        int a1 = (int)(list1.size()*0.99);
        System.out.println("methodA:tp90: "+list1.get(a));
        System.out.println("methodA:tp99: "+list1.get(a1));

        int b = (int)(list1.size()*0.9);
        int b1 = (int)(list1.size()*0.99);
        System.out.println("methodB:tp90: " +list1.get(b));
        System.out.println("methodB:tp99: " +list1.get(b1));

        int c = (int)(list1.size()*0.9);
        int c1 = (int)(list1.size()*0.99);
        System.out.println("methodC:tp90: " +list1.get(c));
        System.out.println("methodC:tp99: " +list1.get(c1));


    }



    private void  remove(Long now ,Map<Long,Long> maps){

    }
}
